home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / security / log_tcp_6.0alpha.shar / from_tli.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-02  |  8.3 KB  |  305 lines

  1. #ifdef TLI
  2.  
  3.  /*
  4.   * from_tli() determines the type of transport (connected, unconnected), and
  5.   * the name and address of the host at the other end of standard input. A
  6.   * host name of "stdin" is returned if the program is run from a tty. All
  7.   * results are in static or allocated memory. from_tli() assumes that its
  8.   * result argument is already initialized with default values.
  9.   * 
  10.   * The software attempts to determine the transport protocol that sits
  11.   * underneath the TLI interface. In the case of TCP/IP, it immedately falls
  12.   * back to familiar concepts and primitives: sockets, DNS, and so on, so
  13.   * that we get the same functionality as with socket-based applications. In
  14.   * all other cases the network addres results will be in some sort of
  15.   * generic transport-independent form, and functionality will be limited (no
  16.   * remote username lookups and no net/mask address patterns).
  17.   * 
  18.   * The return status is (-1) if the remote host pretends to have someone elses
  19.   * host name, otherwise a zero status is returned.
  20.   * 
  21.   * Diagnostics are reported through syslog(3).
  22.   * 
  23.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  24.   */
  25.  
  26. #ifndef lint
  27. static char sccsid[] = "@(#) from_tli.c 1.1 93/07/02 16:33:49";
  28. #endif
  29.  
  30. /* System libraries. */
  31.  
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <sys/mkdev.h>
  35. #include <sys/tiuser.h>
  36. #include <sys/timod.h>
  37. #include <stdio.h>
  38. #include <syslog.h>
  39. #include <errno.h>
  40. #include <netconfig.h>
  41. #include <netdir.h>
  42.  
  43. extern int errno;
  44. extern char *sys_errlist[];
  45. extern int sys_nerr;
  46. extern int t_errno;
  47. extern char *t_errlist[];
  48. extern int t_nerr;
  49.  
  50. /* Local stuff. */
  51.  
  52. #include "log_tcp.h"
  53.  
  54. /* Forward declarations. */
  55.  
  56. static int tli_host();
  57. static int tli_match();
  58. static char *tli_error();
  59. static void tli_sink();
  60.  
  61. /* The following are to be used in assignment context, not in comparisons. */
  62.  
  63. #define    GOOD    1
  64. #define    BAD    0
  65.  
  66. /* from_tli - determine name and address of remote endpoint */
  67.  
  68. int     from_tli(f)
  69. struct from_host *f;
  70. {
  71.     void   *handlep;
  72.     struct netconfig *config;
  73.     struct t_unitdata *unit;
  74.     int     flags;
  75.     struct stat from_stdin;
  76.     struct stat from_netconf;
  77.  
  78.     /*
  79.      * Allocate storage for the endpoint address. t_alloc() finds out for us
  80.      * how large the address can be. Address sizes depend on the underlying
  81.      * transport protocol.
  82.      */
  83.  
  84.     if ((unit = (struct t_unitdata *) t_alloc(0, T_UNITDATA, T_ADDR)) == 0) {
  85.     syslog(LOG_ERR, "t_alloc: %s", tli_error());
  86.     return (0);
  87.     }
  88.  
  89.     /*
  90.      * Get the transport-independent source address. In case of a datagram
  91.      * service, peek at the sender address of the pending datagram without
  92.      * popping the data off the receive queue. This trick works because the
  93.      * data member of the unitdata structure has not been allocated.
  94.      */
  95.  
  96.     if (ioctl(0, TI_GETPEERNAME, &(unit->addr)) >= 0) {    /* assume connected */
  97.     f->sock_type = FROM_CONNECTED;
  98.     } else {
  99.     switch (errno) {
  100.     default:
  101.         if (isatty(0)) {
  102.         f->name = "stdin";
  103.         return (0);
  104.         } else {
  105.         syslog(LOG_ERR, "TI_GETPEERNAME: %m");
  106.         return (0);
  107.         }
  108.     case ENOTCONN:                /* maybe unconnected */
  109.         if (t_rcvudata(0, unit, &flags) < 0) {
  110.         syslog(LOG_ERR, "t_rcvudata: %s", tli_error());
  111.         return (0);
  112.         }
  113.         f->sock_type = FROM_UNCONNECTED;
  114.         f->sink = tli_sink;
  115.         break;
  116.     }
  117.     }
  118.  
  119.     /*
  120.      * In order to map the raw transport address to a human-readable form we
  121.      * must know what transport is involved. Assuming that the network device
  122.      * is a clone device, we must compare the major device number of stdin to
  123.      * the minor device number of the devices listed in the netconfig table.
  124.      */
  125.  
  126.     if (fstat(0, &from_stdin) != 0) {
  127.     syslog(LOG_ERR, "fstat(stdin): %m");
  128.     return (0);
  129.     }
  130.     if ((handlep = setnetconfig()) == 0) {
  131.     syslog(LOG_ERR, "setnetconfig: %m");
  132.     return (0);
  133.     }
  134.     while (config = getnetconfig(handlep)) {
  135.     if (stat(config->nc_device, &from_netconf) == 0) {
  136.         if (minor(from_netconf.st_rdev) == major(from_stdin.st_rdev))
  137.         break;
  138.     }
  139.     }
  140.     if (config == 0) {
  141.     syslog(LOG_ERR, "unable to identify transport protocol");
  142.     return (0);
  143.     }
  144.  
  145.     /*
  146.      * Someone else may clobber the getnetconfig() result, so we'd better
  147.      * acquire our private copy.
  148.      */
  149.  
  150.     if ((config = getnetconfigent(config->nc_netid)) == 0) {
  151.     syslog(LOG_ERR, "getnetconfigent(%s): %s",
  152.            config->nc_netid, nc_sperror());
  153.     return (0);
  154.     }
  155.  
  156.     /*
  157.      * Now that we know the underlying transport protocol, map the address to
  158.      * a human-readble form, and determine the host name. Do DNS lookups if
  159.      * it turns out that we are using an IP transport, after all. Otherwise,
  160.      * use the transport-independent method and stick to generic network
  161.      * addresses. XXX hard-coded protocol family name.
  162.      */
  163.  
  164.     if (strcasecmp(config->nc_protofmly, "inet") == 0) {
  165.     return (ip_host(f, (struct sockaddr_in *) (unit->addr.buf)));
  166.     } else {
  167.     return (tli_host(f, &(unit->addr), config));
  168.     }
  169. }
  170.  
  171. /* tli_host - map TLI transport address to human-readable address and name */
  172.  
  173. static int tli_host(f, taddr, config)
  174. struct from_host *f;
  175. struct netbuf *taddr;
  176. struct netconfig *config;
  177. {
  178.     struct nd_hostservlist *service;
  179.  
  180.     /*
  181.      * Given the transport type we know how to map the transport address to
  182.      * human-readable address, and how to map it to a host name. All results
  183.      * are dynamically allocated so we do not need to make copies. XXX Some
  184.      * transports may not have a universal textual address representation. In
  185.      * those cases we will not be able to verify the host name.
  186.      */
  187.  
  188.     if ((f->addr = taddr2uaddr(config, taddr)) == 0)
  189.     f->addr = FROM_UNKNOWN;
  190.  
  191.     if (netdir_getbyaddr(config, &service, taddr) != ND_OK)
  192.     return (0);
  193.     f->name = service->h_hostservs->h_host;
  194.  
  195.     /*
  196.      * Verify that the host name does not belong to someone else. If host
  197.      * name verification fails, pretend that the host name lookup failed.
  198.      */
  199.  
  200.     if (tli_match(config, service->h_hostservs, f->addr)) {
  201.     return (0);
  202.     } else {
  203.     f->name = FROM_UNKNOWN;
  204.     return (-1);                /* verification failed */
  205.     }
  206. }
  207.  
  208. /* tli_match - determine if host name matches transport address */
  209.  
  210. static int tli_match(config, service, uaddr)
  211. struct netconfig *config;
  212. struct nd_hostserv *service;
  213. char   *uaddr;
  214. {
  215.     struct nd_addrlist *addr_list;
  216.     char   *ua;
  217.     int     i;
  218.  
  219.     if (netdir_getbyname(config, service, &addr_list) != ND_OK) {
  220.  
  221.     /*
  222.      * Unable to verify that the name matches the address. This may
  223.      * be a transient problem or a botched name server setup. We decide
  224.      * to play safe.
  225.      */
  226.  
  227.     syslog(LOG_ERR, "netdir_getbyname(%s): host address lookup failed",
  228.            service->h_host);
  229.     return (BAD);
  230.  
  231.     } else {
  232.  
  233.     /*
  234.      * Look up the host address in the address list we just got. The
  235.      * comparison is done on the textual representation, because the
  236.      * transport address is an opaque structure that may have holes.
  237.      */
  238.  
  239.     for (i = 0; i < addr_list->n_cnt; i++) {
  240.         if (ua = taddr2uaddr(config, &(addr_list->n_addrs[i]))) {
  241.         if (strcmp(ua, uaddr) == 0)
  242.             return (GOOD);
  243.         free(ua);
  244.         }
  245.     }
  246.  
  247.     /*
  248.      * The host name does not map to the original host address. Perhaps
  249.      * someone has compromised a name server. More likely someone botched
  250.      * it, but that could be dangerous, too.
  251.      */
  252.  
  253.     syslog(LOG_ERR, "host name/address mismatch: %s != %s",
  254.            uaddr, service->h_host);
  255.     return (BAD);
  256.     }
  257. }
  258.  
  259. /* tli_error - convert tli error number to text */
  260.  
  261. static char *tli_error()
  262. {
  263.     static char buf[40];
  264.  
  265.     if (t_errno != TSYSERR) {
  266.     if (t_errno < 0 || t_errno >= t_nerr) {
  267.         sprintf(buf, "Unknown TLI error %d", t_errno);
  268.         return (buf);
  269.     } else {
  270.         return (t_errlist[t_errno]);
  271.     }
  272.     } else {
  273.     if (errno < 0 || errno >= sys_nerr) {
  274.         sprintf(buf, "Unknown UNIX error %d", errno);
  275.         return (buf);
  276.     } else {
  277.         return (sys_errlist[errno]);
  278.     }
  279.     }
  280. }
  281.  
  282. /* tli_sink - absorb unreceived datagram */
  283.  
  284. static void tli_sink()
  285. {
  286.     struct t_unitdata *unit;
  287.     int     flags;
  288.  
  289.     /*
  290.      * Something went wrong. Absorb the datagram to keep inetd from looping.
  291.      * Allocate storage for address, control and data. If that fails, sleep
  292.      * for a couple of seconds in an attempt to keep inetd from looping too
  293.      * fast.
  294.      */
  295.  
  296.     if ((unit = (struct t_unitdata *) t_alloc(0, T_UNITDATA, T_ALL)) == 0) {
  297.     syslog(LOG_ERR, "t_alloc: %s", tli_error());
  298.     sleep(5);
  299.     } else {
  300.     (void) t_rcvudata(0, unit, &flags);
  301.     }
  302. }
  303.  
  304. #endif /* TLI */
  305.